package org.neuroninterworks.midi.seq64;

/*
 *	MidiInDump.java
 *
 *	This file is part of jsresources.org
 */

/*
 * Copyright (c) 1999 - 2001 by Matthias Pfisterer
 * Copyright (c) 2003 by Florian Bomers
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
|<---            this code is formatted to fit into 80 columns             --->|
 */
import java.io.IOException;

import javax.sound.midi.Transmitter;
import javax.sound.midi.Receiver;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.Synthesizer;

/*	If the compilation fails because this class is not available,
get gnu.getopt from the URL given in the comment below.
 */
import gnu.getopt.Getopt;

/**	<titleabbrev>MidiInDump</titleabbrev>
<title>Listens to a MIDI port and dump the received event to the console</title>

<formalpara><title>Purpose</title>
<para>Listens to a MIDI port and dump the received event to the console.</para></formalpara>

<formalpara><title>Usage</title>
<para>
<cmdsynopsis>
<command>java MidiInDump</command>
<arg choice="plain"><option>-l</option></arg>
</cmdsynopsis>
<cmdsynopsis>
<command>java MidiInDump</command>
<arg choice="plain"><option>-d <replaceable>devicename</replaceable></option></arg>
<arg choice="plain"><option>-n <replaceable>device#</replaceable></option></arg>
</cmdsynopsis>
</para></formalpara>

<formalpara><title>Parameters</title>
<variablelist>
<varlistentry>
<term><option>-l</option></term>
<listitem><para>list the availabe MIDI devices</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-d <replaceable>devicename</replaceable></option></term>
<listitem><para>reads from named device (see <option>-l</option>)</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-n <replaceable>device#</replaceable></option></term>
<listitem><para>reads from device with given index (see <option>-l</option>)</para></listitem>
</varlistentry>
</variablelist>
</formalpara>

<formalpara><title>Bugs, limitations</title>
<para>
For the Sun J2SDK 1.3.x or 1.4.0, MIDI IN does not work. See the <olink targetdoc="faq_midi" targetptr="faq_midi">FAQ</olink> for alternatives.
</para></formalpara>

<formalpara><title>Source code</title>
<para>
<ulink url="MidiInDump.java.html">MidiInDump.java</ulink>,
<ulink url="DumpReceiver.java.html">DumpReceiver.java</ulink>,
<ulink url="MidiCommon.java.html">MidiCommon.java</ulink>,
<ulink url="http://www.urbanophile.com/arenn/hacking/download.html">gnu.getopt.Getopt</ulink>
</para>
</formalpara>

 */
public class MidiInDump {

    /**	Flag for debugging messages.
    If true, some messages are dumped to the console
    during operation.
     */
    private static boolean DEBUG = true;

    public static void main(String[] args)
            throws Exception {

        /*
         *	The device name/index to listen to.
         */
        String strDeviceName = null;
        int nDeviceIndex = -1;
        boolean bUseDefaultSynthesizer = false;
        // TODO: synchronize options with MidiPlayer

        //MidiCommon.listDevicesAndExit(true, false);
        
        /*
         *	Parsing of command-line options takes place...
         */
        Getopt g = new Getopt("MidiInDump", args, "hlsd:n:D");
        int c;
        while ((c = g.getopt()) != -1) {
            switch (c) {
                case 'h':
                    printUsageAndExit();

                case 'l':
                    MidiCommon.listDevicesAndExit(true, false);

                case 's':
                    bUseDefaultSynthesizer = true;
                    break;

                case 'd':
                    strDeviceName = g.getOptarg();
                    if (DEBUG) {
                        out("MidiInDump.main(): device name: " + strDeviceName);
                    }
                    break;

                case 'n':
                    nDeviceIndex = Integer.parseInt(g.getOptarg());
                    if (DEBUG) {
                        out("MidiInDump.main(): device index: " + nDeviceIndex);
                    }
                    break;

                case 'D':
                    DEBUG = true;
                    break;

                case '?':
                    printUsageAndExit();

                default:
                    out("MidiInDump.main(): getopt() returned " + c);
                    break;
            }
        }
        strDeviceName = "Launchpad";

        if ((strDeviceName == null) && (nDeviceIndex < 0)) {
            out("device name/index not specified!");
            printUsageAndExit();
        }

        MidiDevice.Info info;
        if (strDeviceName != null) {
            info = MidiCommon.getMidiDeviceInfo(strDeviceName, false);
        } else {
            info = MidiCommon.getMidiDeviceInfo(nDeviceIndex);
        }
        if (info == null) {
            if (strDeviceName != null) {
                out("no device info found for name " + strDeviceName);
            } else {
                out("no device info found for index " + nDeviceIndex);
            }
            System.exit(1);
        }
        MidiDevice inputDevice = null;
        try {
            inputDevice = MidiSystem.getMidiDevice(info);
            inputDevice.open();
        } catch (MidiUnavailableException e) {
            out(e);
        }
        if (inputDevice == null) {
            out("wasn't able to retrieve MidiDevice");
            System.exit(1);
        }
        Receiver r = new DumpReceiver(System.out);
        try {
            Transmitter t = inputDevice.getTransmitter();
            t.setReceiver(r);
        } catch (MidiUnavailableException e) {
            out("wasn't able to connect the device's Transmitter to the Receiver:");
            out(e);
            inputDevice.close();
            System.exit(1);
        }
        if (bUseDefaultSynthesizer) {
            Synthesizer synth = MidiSystem.getSynthesizer();
            synth.open();
            r = synth.getReceiver();
            try {
                Transmitter t = inputDevice.getTransmitter();
                t.setReceiver(r);
            } catch (MidiUnavailableException e) {
                out("wasn't able to connect the device's Transmitter to the default Synthesizer:");
                out(e);
                inputDevice.close();
                System.exit(1);
            }
        }
        out("now running; interupt the program with [ENTER] when finished");

        try {
            System.in.read();
        } catch (IOException ioe) {
        }
        inputDevice.close();
        out("Received " + ((DumpReceiver) r).seCount + " sysex messages with a total of " + ((DumpReceiver) r).seByteCount + " bytes");
        out("Received " + ((DumpReceiver) r).smCount + " short messages with a total of " + ((DumpReceiver) r).smByteCount + " bytes");
        out("Received a total of " + (((DumpReceiver) r).smByteCount + ((DumpReceiver) r).seByteCount) + " bytes");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            if (DEBUG) {
                out(e);
            }
        }
    }

    private static void printUsageAndExit() {
        out("MidiInDump: usage:");
        out("  java MidiInDump -h");
        out("    gives help information");
        out("  java MidiInDump -l");
        out("    lists available MIDI devices");
        out("  java MidiInDump [-D] [-d <input device name>] [-n <device index>]");
        out("    -d <input device name>\treads from named device (see '-l')");
        out("    -n <input device index>\treads from device with given index(see '-l')");
        out("    -D\tenables debugging output");
        System.exit(1);
    }

    private static void out(String strMessage) {
        System.out.println(strMessage);
    }

    private static void out(Throwable t) {
        if (DEBUG) {
            t.printStackTrace();
        } else {
            out(t.toString());
        }
    }
}
/*** MidiInDump.java ***/

